package com.ildepinc.persistence.abstracts;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;

import com.ildepinc.persistence.interfaces.JdbcConnectionBehaviour;
import com.ildepinc.persistence.interfaces.JdbcDriverBehaviour;

public abstract class JdbcConnectionBase implements JdbcConnectionBehaviour {
  private Connection connection;
  private JdbcDriverBehaviour jdbcDriver;

  @Override
  public Connection doConnect() throws Exception {
    Class.forName(this.jdbcDriver.getDriverClass());
    String jdbcUrl = this.jdbcDriver.composeFullUrl();
    this.connection = DriverManager.getConnection(jdbcUrl, this.jdbcDriver.getUser(), this.jdbcDriver.getPassword());
    if(this.jdbcDriver.getDatabaseEngine().equals("derby")) {
      // rif: https://stackoverflow.com/questions/31804210/derby-auto-increment-by-100-when-specified-as-1
      System.setProperty("derby.language.sequence.preallocator", "1");
    }
    return this.connection;
  }

  @Override
  public void doDisconnect() throws Exception {
    if (!this.connection.isClosed()) {
      this.connection.close();
    }
    this.connection = null;
  }

  @Override
  public Boolean doesSchemaExists(String schemaName) throws Exception {
    Boolean result = Boolean.valueOf(false);
    ResultSet schemas = this.getDatabaseMetadata().getSchemas();
    String schema = null;
    while (schemas.next()) {
      schema = schemas.getString("TABLE_SCHEM");
      if (schema.toLowerCase().equals(schemaName.toLowerCase())) {
        result = Boolean.valueOf(true);
        break;
      }
    }
    return result;
  }

  @Override
  public Boolean doesTableExists(String schemaName, String tableName) throws Exception {
    Boolean result = Boolean.valueOf(false);
    ResultSet tables = null;
    String table = null;
    String schema = null;
    tables = this.getDatabaseMetadata().getTables(null, null, null, new String[] { "TABLE" });
    while (tables.next()) {
      schema = tables.getString("TABLE_SCHEM");
      table = tables.getString("TABLE_NAME");
      if ((schema.toLowerCase().equals(schemaName.toLowerCase()))
          && (table.toLowerCase().equals(tableName.toLowerCase()))) {
        result = Boolean.valueOf(true);
        break;
      }
    }
    return result;
  }

  @Override
  public Connection getConnection() {
    return this.connection;
  }

  @Override
  public DatabaseMetaData getDatabaseMetadata() throws Exception {
    DatabaseMetaData databaseMetaData = null;
    databaseMetaData = this.connection.getMetaData();
    return databaseMetaData;
  }

  @Override
  public JdbcDriverBehaviour getJdbcDriver() {
    return this.jdbcDriver;
  }

  @Override
  public void setConnection(Connection connection) {
    this.connection = connection;
  }

  @Override
  public void setJdbcDriver(JdbcDriverBehaviour jdbcDriver) {
    this.jdbcDriver = jdbcDriver;
  }

  protected void clear() {
    this.connection = null;
    this.jdbcDriver = null;
  }
}
